#!/usr/bin/env python
#encoding : utf-8

import jinja2
from utils import import_var, import_builtin, to_unicode, gen_uobj

_default_encoding = lambda : 'utf-8'

class TemplateEngineException(Exception): pass

class TemplateEngineBase(object):
    def __init__(self, **args): pass

    def _load_template(self, template=None, **args): pass

    def get_internal_obj(self):
        return None

    def render(self, template=None, data={}, **args):
        raise TemplateEngineException('render method is not implemented')

class Jinja2TemplateEngine(TemplateEngineBase):

	common_vars = { u'import_var': import_var, u'import_builtin': import_builtin, }

	def __init__(self, **kwargs):
		self._jinja2 = __import__('jinja2')

		if 'template_root' not in kwargs:
			raise TemplateEngineException('Template root directory path required')
		template_encoding = kwargs.get('template_encoding', _default_encoding())
		self._data_encoding = kwargs.get('data_encoding', _default_encoding())
		self._output_encoding = kwargs.get('output_encoding', None)

		env_init_args = {'loader' : self._jinja2.FileSystemLoader(kwargs['template_root'], template_encoding),}
		env_init_args.update(kwargs.get('env_init', {}))
		self._env = self._jinja2.Environment(**env_init_args)

		def my_import(name):
			mod = __import__(name)
			components = name.split('.')
			for comp in components[1:]:
				mod = getattr(mod, comp)
			return mod

		# enable custom filters
		if 'filters' in kwargs:
			for f in kwargs['filters']:
				m = my_import(f)
				for i in dir(m):
					if i.startswith('_CustomFilter_'):
						self._env.filters[i[14:]] = m.__dict__[i]


	def _load_template(self, template=None, from_string=None):
		if from_string:
			return self._env.from_string(template)
		return self._env.get_template(template)

	def get_internal_obj(self):
		return self._env

	def render(self, template=None, data={ }, **kwargs):
		data.update(self.common_vars)
		udata = {}
		for k in data.iterkeys():
			udata[to_unicode(k, self._data_encoding)] = gen_uobj(data[k], self._data_encoding)
		o_template = self._load_template(template, kwargs.get('from_string', False))
		output = o_template.render(udata)
		if self._output_encoding:
			return output.encode(self._output_encoding, 'ignore')
		return output


engines = {} 
default_engine = None 

engine_list = { 'jinja2': Jinja2TemplateEngine,}

def tmpl_engine_config(engine_name, template_encoding=_default_encoding(), data_encoding=_default_encoding(), output_encoding=None, default=False, **kwargs):
	if not engine_name:
		raise TemplateEngineException('Template engine name required')

	kwargs['template_encoding'] = template_encoding
	kwargs['data_encoding'] = data_encoding
	kwargs['output_encoding'] = output_encoding

	if engine_name not in engine_list:
		raise TemplateEngineException('Unsupported template engine: %s' % engine_name)

	engines[engine_name] = engine_list[engine_name](**kwargs)

	global default_engine
	if default:
		default_engine = engine_name


def get_engine(engine_name=None):
	if not len(engines):
		raise TemplateEngineException('No template engine is configurated')
	if not engine_name:
		if not default_engine:
			raise TemplateEngineException('No engine is selected')
		engine_name = default_engine
	if engine_name not in engines:
		raise TemplateEngineException('Template engine "%s" is not configurated' % engine_name)
	return engines[engine_name]

def render(engine=None, template=None, data={}, **kwargs):
	return get_engine(engine).render(template, data, **kwargs)

if __name__ == "__main__":
	pass
